<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>工厂模式</title>
  <style>
    .root {
      margin: 100px auto;
      width: 500px;
      min-height: 300px;
      border: 2px solid lightsalmon;
      display: flex;
      flex-direction: column;
      align-items: center;
      transition: all .5s;
    }

    item {
      display: block;
      width: 100%;
      height: 50px;
      line-height: 50px;
      text-align: center;
      font-size: 20px;
      font-weight: bold;
      color: black;
      background-color: #e6e6e6;
      border-bottom: 1px solid gray;
      cursor: pointer;
    }
  </style>
</head>

<div class="root">
  <h2>动物园</h2>
</div>

<body>

  <script>

    /** JavaScript 设计模式之一：工厂模式 */

    /**
     * 顾名思义，工厂模式适应于多个对象的创建,可以向工厂一样源源不断的产出相同的产物
     */

    // 以下使用工厂模式实现一个动物园功能
    {
      // 使用构造函数实现工厂模式
      // 动物园动物数组
      const animals = [new Animal('长颈鹿', 3)];
      const root = document.getElementsByClassName('root')[0];
      // 更新页面数据
      const up = function () {
        (function (root) {
          animals.forEach((item, index) => {
            // 创建元素添加到页面
            const el = document.createElement('item');
            el.textContent = item.name;
            el.setAttribute('data-index', index);
            root.appendChild(el)
          })
        })(document.getElementsByClassName('root')[0])
      }
      up();
      // 使用函数
      // 创建工厂函数
      function Factory(name, age) {
        this.name = name;
        this.age = age;
      }
      Factory.prototype.introduce = function () {
        const { name, age = 3 } = this;
        window.alert(`你好，我叫${name},今年${age}岁了~`)
      }
      // 创建构造动物的函数
      function Animal(name, age) {
        return new Factory(name, age)
      }

      // 添加动物
      function addAnimal(name, age) {
        const animal = new Animal(name, age);
        // 创建元素添加到页面
        animals.push(animal);
        const el = document.createElement('item');
        el.textContent = animal.name;
        el.setAttribute('data-index', animals.length - 1);
        root.appendChild(el);
      }

      // 使用事件委派
      root.addEventListener('click', (event) => {
        const _index = +event.target.getAttribute('data-index');
        const animal = animals.find((item, index) => index === _index);
        console.log(animal);
        animal.introduce()
      })
    }


    {
      /** class 工厂模式 */
      class Animal {
        constructor(name, age) {
          this.name = name;
          this.age = age;
        }
        // 所有动物的方法
        introduce() {
          const { name, age } = this;
          window.alert(`你好，我叫${name},今年${age}岁了~`)
        }
      }

      // 动物初始化数组
      const animals = [new Animal('熊猫', 6)];
      const root = document.getElementsByClassName('root')[0];

      animals.forEach((item, index) => {
        // 创建元素添加到页面
        const el = document.createElement('item');
        el.textContent = item.name;
        el.setAttribute('data-index', index);
        root.appendChild(el)
      })

      // 添加
      function addAnimal(name, age) {
        const an = new Animal(name, age);
        animals.push(an);
        // 创建元素添加到页面
        const el = document.createElement('item');
        el.textContent = an.name;
        el.setAttribute('data-index', animals.length - 1);
        root.appendChild(el)
      }

      root.addEventListener('click', (event) => {
        const elIndex = +event.target.getAttribute('data-index');
        const animal = animals.find((item, index) => index === elIndex);
        animal.introduce();
      })

    }


    // 两种代码同时使用会出现bug，查看效果请手动注释







  </script>

</body>

</html>